﻿namespace Integration.Tests
{
    using System;
    using System.Threading;

    using AlohaAlgorithm;

    using Distributions;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Network;

    using Shared;

    [TestClass]
    public class AlohaAlgorithmIntegrationFixture
    {
        [TestMethod]
        public void ShouldSendTotalKilobytesWithOneClient()
        {
            const int NumberOfClients = 1;

            var successDistribution = new RandomDistribution();

            IAlgorithm algorithm = new AlohaAlgorithm(successDistribution);

            var network = new Network(algorithm, algorithm.FrameSizeInKilobytes, NumberOfClients, 100);

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            Action completed = () => manualResetEvent.Set();

            network.Start(completed, progress => { });

            manualResetEvent.WaitOne(3500, false);
            manualResetEvent.Close();

            Assert.AreEqual(1, network.SuccesfulTransmissions);
            Assert.AreEqual(0, network.FailedTransmissions);
        }

        [TestMethod]
        public void ShouldSendDoubleTotalKilobytesTwoFramesWithOneClient()
        {
            const int NumberOfClients = 1;
            var successDistribution = new RandomDistribution();

            IAlgorithm algorithm = new AlohaAlgorithm(successDistribution);

            var network = new Network(algorithm, algorithm.FrameSizeInKilobytes * 2, NumberOfClients, 100);

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            Action completed = () => manualResetEvent.Set();

            network.Start(completed, progress => { });

            manualResetEvent.WaitOne(5500, false);
            manualResetEvent.Close();

            Assert.AreEqual(1, network.SuccesfulTransmissions);
            Assert.AreEqual(0, network.FailedTransmissions);
        }
        
        [TestMethod]
        public void ShouldMantainIfTheTransmissionWasSuccesful()
        {
            const int NumberOfClients = 1;

            var successDistribution = new RandomDistribution();

            IAlgorithm algorithm = new AlohaAlgorithm(successDistribution);

            var network = new Network(algorithm, algorithm.FrameSizeInKilobytes, NumberOfClients, 100);

            var frame = algorithm.Frames.Peek();

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            Action completed = () => manualResetEvent.Set();

            network.Start(completed, progress => { });

            manualResetEvent.WaitOne(1500, false);
            manualResetEvent.Close();

            var expected = algorithm.WasTransmissionSuccessful(frame);
            Assert.AreEqual(expected, true);
        }

        [TestMethod]
        public void ShouldNotSendAnyFrameWithTenThousandClients()
        {
            const int NumberOfClients = 10000;

            const int KilobytesToTransmit = 10000;

            var successDistribution = new RandomDistribution();

            IAlgorithm algorithm = new AlohaAlgorithm(successDistribution);

            var network = new Network(algorithm, KilobytesToTransmit, NumberOfClients, 100);

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            Action completed = () => manualResetEvent.Set();

            network.Start(completed, progress => { });

            manualResetEvent.WaitOne(1500, false);
            manualResetEvent.Close();

            Assert.AreEqual(0, network.SuccesfulTransmissions);
        }
    }
}
